package entidades;

import gestordeentidades.persistance.DataBaseObject;
import java.util.Objects;
import javafx.beans.property.FloatProperty;
import javafx.beans.property.SimpleFloatProperty;

/**
 * Trabalho DAS - 2014/2015
 *
 * @author a21210380, a21190325, a21210392
 */
public class Rectangulo extends DataBaseObject {
    private Ponto origem;
    private final FloatProperty altura;
    private final FloatProperty largura;
    private final float minSize;

    public Rectangulo(Ponto origem, float altura, float largura, float minSize) {
        this.minSize = minSize;
        if(altura < minSize) {
            altura = minSize;
        }
        if(largura < minSize) {
            largura = minSize;
        }
        
        this.origem = origem;
        this.altura = new SimpleFloatProperty(altura);
        this.largura = new SimpleFloatProperty(largura);
    }

    public Ponto getOrigem() {
        return origem;
    }

    public Rectangulo setOrigem(Ponto origem) {
        this.origem = origem;
        return this;
    }
    
    public float getAltura() {
        return altura.floatValue();
    }

    public float getMinSize() {
        return minSize;
    }

    public Rectangulo setAltura(float altura) {
        if(altura < minSize) {
            altura = minSize;
        }
        this.altura.setValue(altura);
        return this;
    }

    public float getLargura() {
        return largura.floatValue();
    }

    public Rectangulo setLargura(float largura) {
        if(largura < minSize) {
            largura = minSize;
        }
        this.largura.setValue(largura);
        return this;
    }

    public Rectangulo set(float x, float y, float largura, float altura) {
        if(altura < minSize) {
            altura = minSize;
        }
        if(largura < minSize) {
            largura = minSize;
        }
        this.origem.set(x, y);
        this.largura.setValue(largura);
        this.altura.setValue(altura);
        return this;
    }

    public Rectangulo set(Rectangulo rectangulo) {
        this.origem.set(rectangulo.getOrigem());
        this.largura.setValue(rectangulo.getLargura());
        this.altura.setValue(rectangulo.getAltura());
        return this;
    }

    public Ponto getCenter() {
        return new Ponto(origem.getX() + largura.floatValue() / 2, origem.getY() + altura.floatValue() / 2);
    }

    public float area() {
        return this.largura.floatValue() * this.altura.floatValue();
    }

    public float perimetro() {
        return 2 * (this.largura.floatValue() + this.altura.floatValue());
    }

    public boolean contem(float x, float y) {
        return this.origem.getX() <= x && this.origem.getX() + this.largura.floatValue() >= x
                && this.origem.getY() <= y && this.origem.getY() + this.altura.floatValue() >= y;
    }
    
    public boolean efetuaResize(float x, float y) {
        float raio = largura.floatValue()*0.5f;
        Rectangulo r = new Rectangulo(
                new Ponto(origem.getX() + largura.floatValue() - raio, origem.getY() + altura.floatValue() - raio), 
                raio, 
                raio,
                minSize);
        return r.contem(x, y);
    }

    public boolean contem(Rectangulo rectangulo) {
        Ponto rectOrigem = rectangulo.getOrigem();

        float xmin = rectOrigem.getX();
        float xmax = xmin + rectangulo.getLargura();

        float ymin = rectOrigem.getY();
        float ymax = ymin + rectangulo.getAltura();

        return ((xmin > origem.getX() && xmin < origem.getX() + largura.floatValue()) && (xmax > origem.getX() && xmax < origem.getX() + largura.floatValue()))
                && ((ymin > origem.getY() && ymin < origem.getY() + altura.floatValue()) && (ymax > origem.getY() && ymax < origem.getY() + altura.floatValue()));
    }

    public boolean intersecao(Rectangulo rectangulo) {
        Ponto rectOrigem = rectangulo.getOrigem();
        return origem.getX() < rectOrigem.getX() + rectangulo.getLargura() && origem.getX() + largura.floatValue() > rectOrigem.getX()
                && origem.getY() < rectOrigem.getY() + rectangulo.getAltura() && origem.getY() + altura.floatValue() > rectOrigem.getY();
    }
    
    public Ponto getAncora(float x, float y) {
        if(contem(x, y)) {
            return new Ponto(x, y);
        }
        if(x > origem.getX() + largura.floatValue()) {
            x = origem.getX() + largura.floatValue();
        }
        if(y > origem.getY() + altura.floatValue()) {
            y = origem.getY() + altura.floatValue();
        }
        
        if(x < origem.getX()) {
            x = origem.getX();
        }
        if(y < origem.getY()) {
            y = origem.getY();
        }
        
        return new Ponto(x, y);
    }

    @Override
    public String toString() {
        return origem + " A:" + altura + " L:" + largura;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj == this) {
            return true;
        }
        if (obj instanceof Rectangulo) {
            Rectangulo c = (Rectangulo) obj;
            return origem.equals(c.getOrigem()) && altura.floatValue() == c.getAltura() && largura.floatValue() == c.getLargura();
        }
        return false;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 61 * hash + Objects.hashCode(this.origem);
        hash = 61 * hash + Float.floatToIntBits(this.altura.floatValue());
        hash = 61 * hash + Float.floatToIntBits(this.largura.floatValue());
        return hash;
    }

    public FloatProperty alturaProperty() {
        return altura;
    }

    public FloatProperty larguraProperty() {
        return largura;
    }
}
